package com.wolfword.crawler.server.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.PageHelper;
import com.wolfword.common.enums.ClientStatusEnum;
import com.wolfword.crawler.server.dao.ClientLogDao;
import com.wolfword.crawler.server.entity.ClientLogEntity;
import com.wolfword.crawler.server.service.ClientLogService;

@Service
public class ClientLogServiceImpl implements ClientLogService {
	
	/**
	 * 客户端状态：
	 * （1）客户端每分钟汇报一次自己的状态
	 * （2）服务端每3分钟将状态写入到数据库，然后初始化
	 */
	private Map<String, Integer> clientStatus = new HashMap<String, Integer>();
	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	
	@Autowired
	private ClientLogDao clientLogDao;

	
	public ClientLogDao getClientLogDao() {
		return clientLogDao;
	}

	@Resource
	public void setClientLogDao(ClientLogDao clientLogDao) {
		this.clientLogDao = clientLogDao;
	}
	
	public Map<String, Integer> getClientStatus(){
		return clientStatus;
	}
	
	/**
	 * 向客户端状态池中添加数据
	 * @param clientIp
	 * @param clientPort
	 * @param status
	 * @author ServerZhang
	 * @date 2018年1月24日
	 */
	@Override
	public void addClientStatus(String clientIp, Integer clientPort, Integer status ){
		String key = clientIp+":"+clientPort;
		ReadLock readLock = lock.readLock();
		readLock.lock();
		clientStatus.put(key, status);
		readLock.unlock();
	}

	/**
	 * 插入数据
	 *
	 * @param entity
	 *            实体类
	 * @return 主键值
	 */
	@Override
	@Transactional
	public long insert(ClientLogEntity entity) {
		clientLogDao.insert(entity);
		
		return entity.getId();
	}

	/**
	 * 批量插入数据
	 *
	 * @param list
	 *            实体类
	 */
	@Override
	public void batchInsert(List<ClientLogEntity> list) {
		clientLogDao.batchInsert(list);
	}

	/**
	 * 根据主键更新数据
	 *
	 * @param entity
	 *            新数据
	 */
	@Override
	public Integer updateByPrimary(ClientLogEntity entity) {
		return clientLogDao.updateByPrimary(entity);
	}

	/**
	 * 根据主键获取数据
	 *
	 * @param entity
	 *            查询条件
	 * @return 查询结果
	 */
	@Override
	public ClientLogEntity getByPrimary(ClientLogEntity entity) {
		return clientLogDao.getByPrimary(entity);
	}

	/**
	 * 根据查询条件获取一条记录
	 *
	 * @param conditions
	 *            查询条件
	 * @return 查询结果
	 */
	@Override
	public ClientLogEntity getOne(Map<String, Object> conditions) {
		return clientLogDao.getOne(conditions);
	}

	/**
	 * 根据查询条件查询
	 *
	 * @param conditions
	 *            查询条件
	 * @return 结果集
	 */
	@Override
	public List<ClientLogEntity> queryList(Map<String, Object> conditions) {
		return clientLogDao.queryList(conditions);
	}

	/**
	 * 查询所有数据
	 *
	 * @return 结果集
	 */
	@Override
	public List<ClientLogEntity> getAll() {
		return clientLogDao.getAll();
	}
	
	/**
	 * 清理僵尸客户端
	 * 将长时间无请求的客户端置为断开状态
	 * @author ServerZhang
	 * @date 2018年1月24日
	 */
	@Override
	@Transactional
	public void cleanDeadClient(){
		Map<String, Integer> statusMap = getClientStatus();
		WriteLock writeLock = lock.writeLock();
		writeLock.lock();
		
		List<ClientLogEntity> list = new ArrayList<ClientLogEntity>();
		Set<Entry<String, Integer>> entrySet = statusMap.entrySet();
		for(Entry<String, Integer> entry : entrySet){
			String key = entry.getKey();
			Integer value = entry.getValue();
			String[] split = key.split(":");
			if (split.length != 2) {
				continue;
			}
			
			ClientLogEntity entity = new ClientLogEntity();
			entity.setClientIp(split[0]);
			entity.setClientPort(Integer.parseInt(split[1]));
			entity.setClientStatus(value);
			entity.setUpdateTime(new Date());
			list.add(entity);
		}
		
		//1.所有数据状态设为0
		clientLogDao.updateAllStatus(ClientStatusEnum.DISCONNECT.getStatus());
		
		//2.批量修改活动客户端状态
		if (list.size() > 0) {
			clientLogDao.batchUpdateStatus(list);
		}
		
		//3.初始化
		clientStatus = new HashMap<String, Integer>();
		
		writeLock.unlock();
	}
	
	/**
	 * list
	 * @param clientName
	 * @param clientIp
	 * @param clientPort
	 * @param status
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 * @author ServerZhang
	 * @date 2018年1月24日
	 */
	@Override
	public List<ClientLogEntity> list(String clientName, String clientIp, Integer clientPort,
			Integer status,Integer pageIndex,Integer pageSize) {
		PageHelper.startPage(pageIndex, pageSize);
		return clientLogDao.list(clientName, clientIp, clientPort, status);
	}
}
